<?php

declare(strict_types=1);

/**
 * @Author:     Frank
 * @contact     frank_hhm@163.com
 * @Date:       2023-02-04 14:51:42
 * @Last Modified time: 2023-02-23 16:08:16
 */
namespace app\common\services\store;


use frank\base\BaseService;
use frank\exception\CommonException;
use frank\utils\helper\StringHelper;
use frank\utils\helper\ArrayHelper;

use app\common\dao\store\OrderDao;
use app\common\services\store\GoodsService;
use app\common\services\store\order\PaySuccessService;
use app\common\services\store\order\RefundSuccessService;
use app\common\services\pay\RefundService as PayRefundService;

use app\common\enum\pay\PayTypeEnum;
use app\common\enum\pay\PayStatusEnum;
use app\common\enum\pay\RefundSourceEnum;
use app\common\enum\store\order\SourceEnum;
use app\common\enum\store\order\StatusEnum;
use app\common\enum\user\WaterSourceEnum;

use app\common\factory\store\goods\source\Factory as StockFactory;
use app\common\factory\store\order\checkout\Factory as CheckoutFactory;

/**
 * Class OrderService
 */
class OrderService extends BaseService
{

    /**
     * OrderService constructor.
     * @param OrderDao $dao
     */
    public function __construct(OrderDao $dao)
    {
        $this->dao = $dao;
    }

    public function getOrderDetail($param,$with = ['goods','user','address','extract'],$field = ['*'])
    {
        $filter = [];
        if (is_array($param)) {
            $filter = $param;
        } else {
            $filter['id'] = (int)$param;
        }
        $detail = $this->dao->search($filter)->with($with)->field($field)->find();
        if (!$detail) {
            throw new CommonException('数据不存在');
        }
        return $detail->toArray();
    }

     /**
     * 订单详情
     */
    public function getUserOrderDetail($orderId, $uid = 0)
    {
        $filter['id'] = $orderId;
        $uid !== 0 && $filter['user_id'] = $uid;
        if (!$order = $this->dao->search($filter)->with([
            'goods',
            'address', 
            'extract',
        ])->find()
        ) {
            throw new CommonException('订单不存在');
        }
        return $order;
    }

    /**
     * 获取列表
     */
    public function getOrderList(array $where)
    {
        [$page, $limit] = $this->getPageValue();
        $filter = $this->getFilter($where);
        $list = $this->dao->getOrderList($filter, $page, $limit,[],['goods','user']);
        return $list->toArray();
    }

    
	/**
     * 立即购买：获取订单商品(单商品)
     */
    public function getOrderByNow($user, $goodsId, $goodsSkuId, $goodsNum)
    {
        // 商品详情
        $goodsService = GoodsService::instance();

        $goods = $goodsService->search(['id'=>$goodsId])->with(['sku'])->hidden(['content'])->find();
        // 商品购买数量
        $goods['goods_num'] = $goodsNum;
        $goods['goods_sku_id'] = $goodsSkuId;
        return $goodsService->checkOrderGoods([$goods]);
    }

    /**
     * 获取用户订单
     */
    public function getUserOrderListByUid($uid,$filter = []){
        [$page, $limit] = $this->getPageValue();
        $filter['user_id'] = $uid;
        $list = $this->dao->getOrderList($filter, $page, $limit,[],['goods']);
        return $list->toArray();
    }



    /**
     * 用户中心订单列表
     */
    public function getUserList($uid, $type = 'all')
    {
        [$page, $limit] = $this->getPageValue();
        $_this = $this->dao->model()->with(['goods']);
        // 订单数据类型
        // 筛选条件
        $filter = $this->getTypeFilter($type);
        $_this = $_this->where('user_id', '=', $uid)->where($filter);
        return $_this->order(['create_time' => 'desc'])
            ->order('id DESC')->page($page)->paginate($limit);
    }

    public function getCount($where,$type = 'all'){
        $filter = array_merge($where,$this->getTypeFilter($type));
        $_this = $this->dao->search($filter)->with(['goods','refund']);
        return $_this->count();
    }

    private function getTypeFilter($type){
        $filter = [];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';
                // 待付款
                $filter['pay_status'] = PayStatusEnum::PENDING;
                $filter['order_status'] = 2;
                break;
            case 'delivery';
                // 待发货
                $filter['pay_status'] = PayStatusEnum::SUCCESS;
                $filter['order_status'] = 2;
                $filter['delivery_status'] = 0;
                break;
           case 'received';
                // 待收货
                $filter['pay_status'] = PayStatusEnum::SUCCESS;
                $filter['order_status'] = 2;
                $filter['delivery_status'] = 1;
                $filter['receipt_status'] = 0;
                break;
            case 'comment';
                // 待评价
                $filter['order_status']= 1;
                $filter['comment_status'] = 0;
                break;
            case 'refund';
                // $filter['r.status'] = 0;
                break;
            case 'cancel';
                $filter['order_status'] = 4;
                break;
        }
        return $filter;
    }

    private function getFilter($param){
        $filter = [];
        if(!empty($param['search_key']) && !empty($param['search_value'])){
            $filter[$param['search_key']] = $param['search_value'];
        }
        if(!empty($param['pay_type']) && $param['pay_type'] != 'all'){
            $filter['pay_type'] =  $param['pay_type'];
        }
        if(isset($param['order_status']) && $param['order_status'] != 'all'){
            $filter['order_status'] =  $param['order_status'];
        }
        if(!empty($param['soucre']) && $param['soucre'] != 'all'){
            $filter['soucre'] =  $param['soucre'];
        }
        return $filter;
    }



    /**
     * 修改订单价格
     */
    public function updatePrice($orderId,$data)
    {
        $detail = $this->dao->search([
            'id'=>$orderId
        ])->find();
        if ($detail['pay_status']['value']) {
            $this->error = '该订单已支付';
            return false;
        }
        // 实际付款金额
        $payPrice = bcadd($data['order_pay_price'], $data['express_free'] ? '0.00':$data['express_price'], 2);
        if ($payPrice <= 0) {
            $this->error = '订单实付款价格不能为0.00元';
            return false;
        }
        return $detail->save([
                'order_no' => $this->orderNo(), // 修改订单号, 否则微信支付提示重复
                'order_pay_price' => $data['order_pay_price'],
                'update_price' => StringHelper::bcsub($data['order_pay_price'], $detail['order_total_price']),
                'express_price' => $data['express_price'],
                'express_free' => $data['express_free']
            ]) !== false;
    }

    /**
     * 线下支付
     */
    public function offlinePayment($orderId,$data)
    {
        $detail = $this->dao->search([
            'id'=>$orderId
        ])->find();
        if ($detail['pay_status']['value']) {
            $this->error = '该订单已支付';
            return false;
        }
        return  PaySuccessService::instance($detail['order_no'])->onPaySuccess(PayTypeEnum::OFFLINE,[
            'pay_price'=>$data['pay_price']]);
    }

    /**
     * 关闭订单
     */
    public function closeOrder($orderId)
    {
        $detail = $this->dao->search([
            'id'=>$orderId
        ])->find();
        if ($detail['pay_status']['value']) {
            $this->error = '该订单已支付';
            return false;
        }
        if ($detail['delivery_status']['value']) {
            $this->error = '该订单已发货';
            return false;
        }
        return $detail->save([
                'order_status' => StatusEnum::INVALID,
            ]) !== false;
    }

    /**
     * 订单发货完成
     */
    public function deliveryComplete($orderId,$deliveryType)
    {
        $data = [
            'delivery_status'=>1,
            'delivery_time'=>time(),
        ];
        if($deliveryType == 'slef_mention'){
            // 自提核销 标记已收货
            $data['receipt_status'] = 1;
            $data['receipt_time'] = time();
            $data['order_status'] = 1;
            // 处理结算事件

        }
        return $this->dao->update($orderId,$data) !== false;
    }

     /**
     * 取消订单
     */
    public function cancelOrder($data)
    {
        $detail = $this->dao->search([
            'id'=>$data['order_id']
        ])->find();
        if ($detail['delivery_status']['value']) {
            throw new CommonException('该订单不可取消');
        }
        // 订单取消事件
        return $this->transaction(function () use ($detail,$data) {
            if(isset($data['is_cancel'])){
                // 审核
                $statusData['order_status'] =  $data['is_cancel'] == 1 ? 3 : 2;
            }else{
                // 申请提交
                $statusData = ['order_status' => $detail['pay_status']['value'] == PayStatusEnum::SUCCESS ? 4 : 3];
            }
            // 回退商品库存
            StockFactory::getFactory($detail['order_source']['value'])->backGoodsStock($detail['goods'],$detail['order_source_id'],$detail['pay_status']['value']);
            // 未付款的订单
            if ($detail['pay_status']['value'] != PayStatusEnum::SUCCESS) {
                // 回退用户优惠券
            }
            if($statusData['order_status'] == 3){
                // 执行退款操作
                $this->executeRefund($detail);
            }
            // 更新订单状态
            return $detail->save($statusData);
        });
    }

    /**
     * 订单确定收货
     */
    public function receiptOrder($orderId){
        // 验证订单是否合法
        // 条件1: 订单必须配送中
        // 条件2: 订单必须未收货
        $detail =  $this->dao->search(['id'=>$orderId])->find();

        if ($detail['delivery_type']['value'] != 'express' || !$detail['delivery_status']['value'] || $detail['receipt_status']['value'] ) {
            $this->error = '该订单不合法';
            return false;
        }
        return $this->transaction(function () use ($detail) {
            // 更新订单状态
            $data = [
                'receipt_status' => 1,
                'receipt_time' => time(),
                'order_status' => 1
            ];
            $status = $this->dao->update($detail['id'],$data);
            // 执行订单完成后的操作
          
            return $status;
        });
    }

    /**
     * 订单支付事件
     */
    public function onPay($orderId,$payType = PayTypeEnum::WECHAT,$user)
    {
        if (empty($payType)) {
            $this->error = '未选择支付方式';
            return false;
        }
        $detail =  $this->dao->search(['id'=>$orderId])->with([
            'goods'=>['goods'],
        ])->find();
        // 判断订单状态
        if ($detail['order_status']['value'] == StatusEnum::INVALID || time() >= (_strtotime($detail['create_time']) + $detail['invalid_time'])) {
            $this->error = '该订单已失效';
            return false;
        }

        $checkout = CheckoutFactory::getFactory(
            $user,
            $detail['goods'],
            $detail['order_source']['value']
        );
        $status = $checkout->validateGoodsList();

        if (! $checkout->validateGoodsList()) {
            $this->error = $checkout->getError();
            return false;
        }
        // 余额支付
        if ($payType == PayTypeEnum::WALLET) {
            return $this->onPaymentByWallet($detail);
        }
        return $detail;
    }

    /**
     * 当前订单是否允许申请售后
     * @return bool
     */
    public function isAllowRefund($order)
    {
        // 当前时间超出允许申请售后期限
        if (
            $order['receipt_status']['value'] == 1 && time() > _strtotime($order['receipt_time']) + (float)sysconf('store_order_refund_days') * 60 * 60 * 24
        ) {
            return false;
        }
        return true;
    }

    /**
     * 构建微信支付请求的参数
     */
    public function onPaymentByWechat($user, $payType,$order)
    {
        return $payType == PayTypeEnum::WECHAT ? event('WechatPayment',[
            'openid'=>$user['wechat_openid'],
            'order_id'=>$order['id'],
            'order_no'=>$order['order_no'],
            'pay_price'=>$order['order_pay_price'],
            'description'=>$order['goods'][0]['goods_name']??'',
            'source' =>SourceEnum::MASTER
        ]) : [];
    }

    /**
     * 余额支付标记订单已支付
     */
    public function onPaymentByWallet($order)
    {
        $service = PaySuccessService::instance($order['order_no']);
        // 订单支付成功业务处理
        $status = $service->onPaySuccess(PayTypeEnum::WALLET,[
            'pay_price'=>$order['order_pay_price']  //余额支付金额
        ]);
        if (!$status) {
            $this->error = $service->error;
        }
        return $status;
    }

    /**
     * 构建退款
     */
    public function executeRefund($detail, $money = null)
    {
         // 退款金额，如不指定则默认为订单实付款金额
        is_null($money) && $money = $detail['pay_price'];
        // 添加退款单
        return PayRefundService::instance()->execute([
            'source'=>RefundSourceEnum::MASTER,
            'source_id'=>$detail['id'],
            'order_no'=>$detail['order_no'],
            'order_id'=>$detail['id'],
            'pay_price'=>$detail['pay_price'],
            'refund_price'=>$money,
            'refund_status'=>3,
        ],$detail['pay_type']['value']);
    }

    /**
     * 批量更新订单
     */
    public function onBatchUpdate($orderIds, $data)
    {
        return $this->dao->search(['id'=>$orderIds])->update($data);
    }
}
